import tensorflow as tf
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
import os
import matplotlib.pyplot as plt

np.random.seed(777)
tf.random.set_seed(777)

# 2.	使用keras创建线性回归模型完成多变量线性回归的预测
# ①	数据处理
# 1)	加载Advertising数据集（7分）
df = pd.read_csv('Advertising.csv')
print(df.shape)
print(df[:5])

# 3)	进行特征缩放（7分）
data = StandardScaler().fit_transform(df)

# 2)	切分特征和标签（7分）
x = data[:, :-1]
y = data[:, -1:]
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=777, train_size=0.9)
m_train, n = x_train.shape

# ②	模型创建
# 1)	创建容器放入多变量线性回归模型（7分）
L1 = 200
L2 = 300
L3 = 350
model = tf.keras.Sequential([
    tf.keras.layers.Dense(L1, input_dim=n, activation=tf.nn.relu),
    tf.keras.layers.Dense(L2, activation=tf.nn.relu),
    tf.keras.layers.Dense(L3, activation=tf.nn.relu),
    tf.keras.layers.Dense(1, activation=None)
])

# 2)	进行编译，合理选择优化器和损失函数（7分）
alpha = 0.0001
model.compile(
    optimizer=tf.keras.optimizers.Adam(learning_rate=alpha),
    loss=tf.keras.losses.mean_squared_error,
    metrics=[tf.keras.metrics.mean_absolute_error, tf.keras.metrics.mean_absolute_percentage_error]
)

# 3)	进行拟合，自行选择循环次数（7分）
n_epochs = 100
batch_size = 64
history = model.fit(x_train, y_train, batch_size=batch_size, epochs=n_epochs)
spr = 1
spc = 3
spn = 0
plt.figure(figsize=[12, 4])


def do_plotting(title):
    global spn
    spn += 1
    plt.subplot(spr, spc, spn)
    plt.plot(history.history[title])
    plt.title(title)


do_plotting('loss')
do_plotting('mean_absolute_error')
do_plotting('mean_absolute_percentage_error')

# ③	模型预测
# 1)	计算并打印预测值（7分）
pred_test = model.predict(x_test)
diff = pred_test - y_test
print(f'Prediction, True value, Diff')
print(np.c_[pred_test, y_test, diff])

# 2)	保存模型（3分）
ver = 'v1.0'
save_dir = './_save/' + os.path.basename(__file__) + '/' + ver
os.makedirs(save_dir, exist_ok=True)
model.save(save_dir + '/model.tmp.dat')
print('MODEL SAVED')

# Finally show all plotting
plt.show()
